001 /*
002 * Copyright 2006 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.component;
020
021 import java.io.IOException;
022 import java.net.URI;
023 import java.lang.ref.WeakReference;
024
025 import net.dpml.lang.Classpath;
026 import net.dpml.lang.Info;
027 import net.dpml.lang.Part;
028
029 import net.dpml.util.Logger;
030
031 /**
032 * Component composition.
033 *
034 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
035 * @version 1.0.0
036 */
037 public abstract class Composition extends Part implements Directive
038 {
039 private final Directive m_directive;
040 private final Controller m_controller;
041
042 private transient WeakReference m_model;
043
044 /**
045 * Creation of a new abstract composition instance.
046 * @param logger the assigned logging channel
047 * @param info the part info descriptor
048 * @param classpath the part classpath definition
049 * @param controller the part controller
050 * @param directive the part deployment strategy directive
051 * @param label debug label
052 * @exception IOException if an I/O error occurs
053 */
054 public Composition(
055 Logger logger, Info info, Classpath classpath, Controller controller,
056 Directive directive, String label ) throws IOException
057 {
058 super( logger, info, classpath, label );
059
060 if( null == directive )
061 {
062 throw new NullPointerException( "directive" );
063 }
064 m_directive = directive;
065 m_controller = controller;
066 }
067
068 /**
069 * Return the assigned controller.
070 * @return the controller
071 */
072 public Controller getController()
073 {
074 return m_controller;
075 }
076
077 /**
078 * Return the part content or null if the result type is unresolvable
079 * relative to the supplied class argument. Class types recognized over and
080 * above the Part class include Directive, Model, Component and Controller.
081 *
082 * @param c the content class
083 * @return the content
084 * @exception IOException if an IO error occurs
085 */
086 protected Object getContent( Class c ) throws IOException
087 {
088 if( Directive.class.isAssignableFrom( c ) )
089 {
090 return m_directive;
091 }
092 else if( Model.class.isAssignableFrom( c ) )
093 {
094 return getModel();
095 }
096 else if( Component.class.isAssignableFrom( c ) )
097 {
098 return newComponent();
099 }
100 else if( Controller.class.isAssignableFrom( c ) )
101 {
102 return m_controller;
103 }
104 else
105 {
106 return super.getContent( c );
107 }
108 }
109
110 /**
111 * Get the deployment directive.
112 * @return the deployment directive
113 */
114 public Directive getDirective()
115 {
116 return m_directive;
117 }
118
119 /**
120 * Get the deployment model.
121 * @return the deployment model
122 */
123 public Model getModel()
124 {
125 if( null != m_model )
126 {
127 Model model = (Model) m_model.get();
128 if( null != model )
129 {
130 return model;
131 }
132 }
133 try
134 {
135 Model model = m_controller.createModel( this );
136 m_model = new WeakReference( model );
137 return model;
138 }
139 catch( Throwable e )
140 {
141 URI uri = m_controller.getURI();
142 final String error =
143 "Unexpected error while attempting to create a component model."
144 + "\nDirective: " + m_directive;
145 throw new ControlRuntimeException( uri, error, e );
146 }
147 }
148
149 /**
150 * Create and return a new component using the deplyment model established by the part.
151 * @return the component
152 */
153 public Component newComponent()
154 {
155 Model model = getModel();
156 try
157 {
158 return m_controller.createComponent( model );
159 }
160 catch( Throwable e )
161 {
162 URI uri = m_controller.getURI();
163 final String error =
164 "Unexpected error while attempting to create a component."
165 + "\nDirective: " + m_directive;
166 throw new ControlRuntimeException( uri, error, e );
167 }
168 }
169
170 /**
171 * Instantiate a value.
172 * @param args supplimentary arguments
173 * @return the resolved instance
174 * @exception Exception if a deployment error occurs
175 */
176 public Object instantiate( Object[] args ) throws Exception
177 {
178 Component component = newComponent();
179 return component.getProvider().getValue( false );
180 }
181
182 /**
183 * Return true if this object is equal to the supplied object.
184 * @param other the object to evaluate
185 * @return the equality status
186 */
187 public boolean equals( Object other )
188 {
189 if( super.equals( other ) && ( other instanceof Composition ) )
190 {
191 Composition composite = (Composition) other;
192 if( !m_directive.equals( composite.m_directive ) )
193 {
194 return false;
195 }
196 else
197 {
198 if( null == m_controller )
199 {
200 return null == composite.m_controller;
201 }
202 else
203 {
204 return m_controller.equals( composite.m_controller );
205 }
206 }
207 }
208 else
209 {
210 return false;
211 }
212 }
213
214 /**
215 * Return the hashcode for the instance.
216 * @return the instance hashcode
217 */
218 public int hashCode()
219 {
220 int hash = super.hashCode();
221 hash ^= m_directive.hashCode();
222 if( null != m_controller )
223 {
224 hash ^= m_controller.hashCode();
225 }
226 return hash;
227 }
228 }